| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- 'use client';
- // D2 종목 토론 탭 — 통계 헤더 + 글 목록(DefaultListLayout 스타일) + 글쓰기(로그인 게이트).
- // 목록은 SSR 로 받은 initial 데이터를 렌더하고, 페이징은 링크로 처리(?tab=discussion&page=).
- import '@/app/styles/community.scss';
- import Link from 'next/link';
- import { useState } from 'react';
- import { useMemberContext } from '@/contexts/memberProvider';
- import { formatDate } from '@/lib/utils/client';
- import { StockBoardPostsResponse } from '@/types/community';
- import StockWriteForm from './StockWriteForm';
- interface Props {
- code: string;
- stockName?: string|null;
- page: number;
- perPage: number;
- data: StockBoardPostsResponse;
- }
- export default function StockDiscussion({ code, stockName, page, perPage, data }: Props)
- {
- const { member } = useMemberContext();
- const [writing, setWriting] = useState(false);
- const stats = data.stats;
- const list = data.list;
- const startIndex = data.total - (page - 1) * perPage;
- const totalPages = Math.max(Math.ceil(data.total / perPage), 1);
- return (
- <div className='stock-discussion'>
- <div className='stock-discussion__stats'>
- <span>전체 글<strong>{stats.posts.toLocaleString()}</strong></span>
- <span>댓글<strong>{stats.comments.toLocaleString()}</strong></span>
- {stats.lastPostAt && <span>최근 작성<strong>{formatDate(stats.lastPostAt)}</strong></span>}
- </div>
- <div className='stock-discussion__head'>
- <span className='stock-discussion__count'>총 {data.total.toLocaleString()}건</span>
- {member ? (
- !writing && (
- <button type='button' className='stock-write-toggle' onClick={() => setWriting(true)}>
- 글쓰기
- </button>
- )
- ) : null}
- </div>
- {member && writing && (
- <StockWriteForm stockCode={code} stockName={stockName} onDone={() => setWriting(false)} />
- )}
- {!member && (
- <div className='stock-write-login'>
- <Link href='/login'>로그인</Link> 후 토론에 참여할 수 있습니다.
- </div>
- )}
- {list.length === 0 ? (
- <p className='stock-discussion__empty'>등록된 글이 없습니다. 첫 글을 남겨보세요.</p>
- ) : (
- <table className='stock-discussion__table'>
- <caption className='sr-only'>{stockName ?? code} 토론 글 목록 — 번호·제목·작성자·작성일·조회·좋아요</caption>
- <thead>
- <tr>
- <th className='stock-discussion__col--num-h' scope='col'>번호</th>
- <th scope='col'>제목</th>
- <th className='stock-discussion__col--author' scope='col'>작성자</th>
- <th scope='col'>작성일</th>
- <th className='stock-discussion__col--views' scope='col'>조회</th>
- <th scope='col'>추천</th>
- </tr>
- </thead>
- <tbody>
- {list.map((row, i) => (
- <tr key={row.id}>
- <td className='stock-discussion__table-num'>{startIndex - i}</td>
- <td>
- <Link href={`/post/${row.id}`} className='stock-discussion__subject'>
- {row.hasPrediction && <span className='prediction-tag prediction-tag--flat' title='예측 글'>예측</span>}
- <em>{row.subject}</em>
- {row.comments > 0 && <span className='stock-discussion__comments'>[{row.comments}]</span>}
- </Link>
- </td>
- <td className='stock-discussion__col--author'>{row.name || row.sid || '익명'}</td>
- <td className='stock-discussion__table-meta'>{formatDate(row.createdAt)}</td>
- <td className='stock-discussion__col--views stock-discussion__table-meta'>{row.views.toLocaleString()}</td>
- <td className='stock-discussion__table-meta'>{row.likes.toLocaleString()}</td>
- </tr>
- ))}
- </tbody>
- </table>
- )}
- {data.total > perPage && (
- <nav className='track-leaderboard__actions' aria-label='페이지'>
- {page > 1 && (
- <Link href={`/stock/${code}?tab=discussion&page=${page - 1}`} className='track-leaderboard__btn'>이전</Link>
- )}
- <span className='stock-discussion__count'>{page} / {totalPages}</span>
- {page < totalPages && (
- <Link href={`/stock/${code}?tab=discussion&page=${page + 1}`} className='track-leaderboard__btn'>다음</Link>
- )}
- </nav>
- )}
- </div>
- );
- }
|